package com.majie.utils.utils;

import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.Arrays;

/**
 * 数字相关utils
 * 另外相关工具类 org.apache.commons.lang3.math.NumberUtils
 *
 * @author majie
 * @date 2018/6/19.
 */
public class NumberUtils {

    /**
     * 默认小数位数
     */
    private static final int DEFAULT_SCALE = 2;

    /**
     * 将double转换成int
     * 不能转换的抛出参数不合法异常
     */
    public static int double2Int(Double num) {
        double eps = 1e-10;
        if (num - Math.floor(num) < eps) {
            return num.intValue();
        } else {
            throw new IllegalArgumentException("double can't convert to int");
        }
    }

    /**
     * double的加法运算
     */
    private static double add(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }

    /**
     * double的减法运算
     */
    private static double subtract(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    }

    /**
     * double的乘法运算
     */
    public static double multiply(double d1, double d2) {
        BigDecimal b1 = new BigDecimal(Double.toString(d1));
        BigDecimal b2 = new BigDecimal(Double.toString(d2));
        return b1.multiply(b2).doubleValue();
    }

    /**
     * double的除法运算,默认使用四舍五入
     *
     * @param scale 结果保留几位小数
     */
    public static double divide(double d1, double d2, int scale) {
        BigDecimal b1 = new BigDecimal(d1);
        BigDecimal b2 = new BigDecimal(d2);
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * double的除法运算,默认使用四舍五入
     * 默认保留两位小数
     */
    public static double divide(double d1, double d2) {
        BigDecimal b1 = new BigDecimal(d1);
        BigDecimal b2 = new BigDecimal(d2);
        return b1.divide(b2, DEFAULT_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 四舍五入
     *
     * @param num   需要转换的数字
     * @param scale 结果保留几位小数
     * @return double
     */
    public static double round(double num, int scale) {

        int roundingMode = BigDecimal.ROUND_HALF_UP;//表示四舍五入，可以选择其他舍值方式，例如去尾，等等.具体看BigDecimal类
        BigDecimal bd = new BigDecimal(num);
        bd = bd.setScale(scale, roundingMode);
        return bd.doubleValue();
    }

    /**
     * 四舍五入,默认保留两位小数
     *
     * @param nums 需要转换的数字
     * @return double
     */
    public static double round(double nums) {

        int roundingMode = BigDecimal.ROUND_HALF_UP;//表示四舍五入，可以选择其他舍值方式，例如去尾，等等.具体看BigDecimal类
        BigDecimal bd = new BigDecimal(nums);
        bd = bd.setScale(DEFAULT_SCALE, roundingMode);
        return bd.doubleValue();
    }

    /**
     * 查找数组中最接近或者等于的数
     *
     * @param array     需要查找的数组
     * @param targetNum 需要查找的数
     * @return 实际值的index
     */
    public static int binarySearchKey(Long[] array, long targetNum) {
        Arrays.sort(array);
        int left = 0, right;
        for (right = array.length - 1; left != right; ) {
            int midIndex = (right + left) / 2;
            int mid = (right - left);
            long midValue = array[midIndex];
            if (targetNum == midValue) {
                // log.debug("和要查找的数：" + targetNum + "最接近的数：" + midValue);
                return midIndex;
            }

            if (targetNum > midValue) {
                left = midIndex;
            } else {
                right = midIndex;
            }

            if (mid <= 1) {
                break;
            }
        }
        long rightNum = array[right];
        long leftNum = array[left];
        long ret = Math.abs((rightNum - leftNum) / 2) > Math.abs(rightNum - targetNum) ? rightNum : leftNum;
        // log.debug("和要查找的数：" + targetNum + "最接近的数：" + ret);
        return ret == rightNum ? right : left;
    }

    /**
     * 找到 数组中比当前值小或者相等的最近的数
     *
     * @param array     需要查找的数组
     * @param targetNum 需要查找的数
     * @return index
     */
    public static int binarySearchLeftKey(Long[] array, long targetNum) {
        Arrays.sort(array);
        int left = array.length - 1;
        long temp = 0;
        for (int i = 0; i < array.length; i++) {
            if (array[i] == targetNum) {
                return i;
            }
            if (array[i] > targetNum) {
                break;
            }
            if (targetNum - array[i] > 0 && temp > (targetNum - array[i])) {
                temp = targetNum - array[i];
                left = i;
            }
        }
        return left;
    }

    /**
     * 获取百分比
     *
     * @param molecular   分子
     * @param denominator 分母
     */
    public static String getPercent(long molecular, long denominator) {
        String percent = "0%";
        if (molecular == 0 || denominator == 0) {
            return percent;
        }
        // 创建一个数值格式化对象
        NumberFormat numberFormat = NumberFormat.getInstance();
        // 设置精确到小数点后2位
        numberFormat.setMaximumFractionDigits(DEFAULT_SCALE);
        percent = numberFormat.format((float) molecular / (float) denominator * 100) + "%";

        return percent;

    }


    public static void main(String[] args) {
        System.out.println(getPercent(1, 3));

        System.out.println("------------------");
        System.out.println(round(3.1111, 2));
        System.out.println(round(3.116));


        System.out.println("------------------");
        System.out.println(add(1.1, 2.22));
        System.out.println(multiply(1.1, 2.22));


        System.out.println("------------------");
        System.out.println(divide(1.1, 2.22, 2));
        System.out.println(divide(1.18, 2.22));

        System.out.println("------------------");
        System.out.println(subtract(1.1, 2.22));

        System.out.println(double2Int(2.00));
    }

}
